﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;

namespace WcfInspectorLib
{
    public class AuthorizeBehaviorAttribute : Attribute,
        IServiceBehavior, IEndpointBehavior, IContractBehavior
    {
        public const string DefaultNameSpace = "http://www.alexywt.com/wcf/authorize";

        public string NameSpace { get; set; }

        public bool Ignore { get; set; }

        public AuthorizeBehaviorAttribute() 
        {
            NameSpace = DefaultNameSpace;
            Ignore = false;
        }

        #region ServiceBehavior
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
                {
                    foreach (DispatchOperation op in endpointDispatcher.DispatchRuntime.Operations)
                    {
                        Assembly assembly = Assembly.GetExecutingAssembly();//契约接口所在程序集
                        var types = assembly.GetTypes();
                        bool ignore = false;
                        foreach (var t in types)
                        {
                            var type = t.GetInterface(endpointDispatcher.ContractName);//获取对应契约名称的接口
                            if (type != null)
                            {
                                string action = op.Action;
                                string methodName = action.Substring(action.LastIndexOf("/") + 1);
                                AuthorizeBehaviorAttribute attribute = type.GetMethod(methodName).GetCustomAttribute<AuthorizeBehaviorAttribute>();
                                if (attribute != null)
                                {
                                    //首先检查当前请求方法是否有标注AuthorizeAttribute
                                    ignore = attribute.Ignore;//是否忽略
                                    break;
                                }

                                attribute = type.GetCustomAttribute<AuthorizeBehaviorAttribute>();
                                if (attribute != null)
                                {
                                    //再次检查接口上有无标注AuthorizeAttribute
                                    ignore = attribute.Ignore;
                                    break;
                                }

                                break;
                            }
                        }
                        if (ignore)
                        { 
                        
                        }
                    }
                }
            }
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {

        }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {

        }
        #endregion

        #region EndpointBehavior
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {

        }

        public void Validate(ServiceEndpoint endpoint)
        {

        }
        #endregion

        #region ContractBehavior
        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {

        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {

        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {

        }
        #endregion
    }
}
